home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / nt / source.exe / POSIX / FIND / FIND.C < prev    next >
C/C++ Source or Header  |  1992-10-29  |  6KB  |  213 lines

  1. /*-
  2.  * Copyright (c) 1991 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Cimarron D. Taylor of the University of California, Berkeley.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. static char sccsid[] = "@(#)find.c    5.3 (Berkeley) 5/25/91";
  39. #endif /* not lint */
  40.  
  41. #ifdef DF_POSIX /* DF_MSS */
  42. #include <misc.h>
  43. #include <bsdlib.h>
  44. #endif
  45.  
  46. #include <sys/types.h>
  47. #include <sys/stat.h>
  48.  
  49. #ifdef _POSIX_SOURCE /* DF_MSS */
  50. #include <errno.h>
  51. #else
  52. #include <sys/errno.h>
  53. #endif
  54.  
  55. #include <fts.h>
  56. #include <stdio.h>
  57. #include <string.h>
  58. #include <stdlib.h>
  59. #include "find.h"
  60.  
  61. /*
  62.  * find_formplan --
  63.  *    process the command line and create a "plan" corresponding to the
  64.  *    command arguments.
  65.  */
  66. PLAN *
  67. #if __STDC__
  68. find_formplan (char **argv)
  69. #else
  70. find_formplan(argv)
  71.     char **argv;
  72. #endif
  73. {
  74.     PLAN *plan, *tail, *new;
  75.     PLAN *c_print __P((void)), *find_create __P((char ***));
  76.     PLAN *not_squish __P((PLAN *)), *or_squish __P((PLAN *));
  77.     PLAN *paren_squish __P((PLAN *));
  78.  
  79.     /*
  80.      * for each argument in the command line, determine what kind of node
  81.      * it is, create the appropriate node type and add the new plan node
  82.      * to the end of the existing plan.  The resulting plan is a linked
  83.      * list of plan nodes.  For example, the string:
  84.      *
  85.      *    % find . -name foo -newer bar -print
  86.      *
  87.      * results in the plan:
  88.      *
  89.      *    [-name foo]--> [-newer bar]--> [-print]
  90.      *
  91.      * in this diagram, `[-name foo]' represents the plan node generated
  92.      * by c_name() with an argument of foo and `-->' represents the
  93.      * plan->next pointer.
  94.      */
  95.     for (plan = NULL; *argv;) {
  96.         if (!(new = find_create(&argv)))
  97.             continue;
  98.         if (plan == NULL)
  99.             tail = plan = new;
  100.         else {
  101.             tail->next = new;
  102.             tail = new;
  103.         }
  104.     }
  105.     
  106.     /*
  107.      * if the user didn't specify one of -print, -ok or -exec, then -print
  108.      * is assumed so we add a -print node on the end.  It is possible that
  109.      * the user might want the -print someplace else on the command line,
  110.      * but there's no way to know that.
  111.      */
  112.     if (!isoutput) {
  113.         new = c_print();
  114.         if (plan == NULL)
  115.             tail = plan = new;
  116.         else {
  117.             tail->next = new;
  118.             tail = new;
  119.         }
  120.     }
  121.     
  122.     /*
  123.      * the command line has been completely processed into a search plan
  124.      * except for the (, ), !, and -o operators.  Rearrange the plan so
  125.      * that the portions of the plan which are affected by the operators
  126.      * are moved into operator nodes themselves.  For example:
  127.      *
  128.      *    [!]--> [-name foo]--> [-print]
  129.      *
  130.      * becomes
  131.      *
  132.      *    [! [-name foo] ]--> [-print]
  133.      *
  134.      * and
  135.      *
  136.      *    [(]--> [-depth]--> [-name foo]--> [)]--> [-print]
  137.      *
  138.      * becomes
  139.      *
  140.      *    [expr [-depth]-->[-name foo] ]--> [-print]
  141.      *
  142.      * operators are handled in order of precedence.
  143.      */
  144.  
  145.     plan = paren_squish(plan);        /* ()'s */
  146.     plan = not_squish(plan);        /* !'s */
  147.     plan = or_squish(plan);            /* -o's */
  148.     return(plan);
  149. }
  150.  
  151. FTS *tree;            /* pointer to top of FTS hierarchy */
  152.  
  153. /*
  154.  * find_execute --
  155.  *    take a search plan and an array of search paths and executes the plan
  156.  *    over all FTSENT's returned for the given search paths.
  157.  */
  158. void
  159. #if __STDC__
  160. find_execute (PLAN *plan, char **paths)
  161. #else
  162. find_execute(plan, paths)
  163.     PLAN *plan;        /* search plan */
  164.     char **paths;        /* array of pathnames to traverse */
  165. #endif
  166. {
  167.     register FTSENT *entry;
  168.     PLAN *p;
  169.     
  170.     if (!(tree = fts_open(paths, ftsoptions, (int (*) __P((const FTSENT *, const FTSENT *)))NULL)))
  171.         err("ftsopen: %s", strerror(errno));
  172.  
  173.     while ((entry = fts_read(tree)) != NULL) {
  174.         switch(entry->fts_info) {
  175.         case FTS_D:
  176.             if (isdepth)
  177.                 continue;
  178.             break;
  179.         case FTS_DP:
  180.             if (!isdepth)
  181.                 continue;
  182.             break;
  183.         case FTS_DNR:
  184.         case FTS_ERR:
  185.         case FTS_NS:
  186.             (void)fprintf(stderr, "find: %s: %s\n", 
  187.                 entry->fts_path, strerror(errno));
  188.             continue;
  189.         case FTS_SL:
  190.             if (entry->fts_level == FTS_ROOTLEVEL) {
  191.                 (void)fts_set(tree, entry, FTS_FOLLOW);
  192.                 continue;
  193.             }
  194.             break;
  195.         }
  196.  
  197. #define    BADCH    " \t\n\\'\""
  198.         if (isxargs && strpbrk(entry->fts_path, BADCH)) {
  199.             (void)fprintf(stderr,
  200.                 "find: illegal path: %s\n", entry->fts_path);
  201.             continue;
  202.         }
  203.          
  204.         /*
  205.          * call all the functions in the execution plan until one is
  206.          * false or all have been executed.  This is where we do all
  207.          * the work specified by the user on the command line.
  208.          */
  209.         for (p = plan; p && (p->eval)(p, entry); p = p->next);
  210.     }
  211.     (void)fts_close(tree);
  212. }
  213.